<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2016 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: 刘志淳 <chun@engineer.com>
// +----------------------------------------------------------------------

namespace think\console\command;

use think\console\Command;
use think\console\Input;
use think\console\input\Argument;
use think\console\Output;
use think\facade\App;
use think\facade\Config;
use think\facade\Env;
use think\facade\Log;

abstract class Make extends Command
{

    protected $type;

    abstract protected function getStub();

    protected function configure()
    {
        $this->addArgument('name', Argument::REQUIRED, "The name of the class");
    }

    /**
     * 这就是命名执行的方法
     * @param  Input  $input  [description]
     * @param  Output $output [description]
     * @return [type]         [description]
     */
    protected function execute(Input $input, Output $output)
    {
        // 来获取我们命令所需要创建的文件  data\model\Test
        $name = trim($input->getArgument('name'));

        // 对于$name所需要创建的文件进行处理
        // 1.命名中以app开头的那么不做处理
        // 2.不是app开头那么就会做处理，同时也会在 data\model\Test 前面添加app
        $classname = $this->getClassName($name);
        // Log::write('$classname === >> : '.$classname);
        // 就是根据$classname创建对应的文件
        // 创建的方式根据与模板
        $pathname = $this->getPathName($classname);
        //Log::write('$pathname === >> : '.$pathname);

        if (is_file($pathname)) {
            $output->writeln('<error>' . $this->type . ' already exists!</error>');
            return false;
        }

        if (!is_dir(dirname($pathname))) {
            mkdir(dirname($pathname), 0755, true);
        }

        file_put_contents($pathname, $this->buildClass($classname));

        $output->writeln('<info>' . $this->type . ' created successfully.</info>');

    }

    protected function buildClass($name)
    {
        $stub = file_get_contents($this->getStub());

        $namespace = trim(implode('\\', array_slice(explode('\\', $name), 0, -1)), '\\');

        $class = str_replace($namespace . '\\', '', $name);

        return str_replace(['{%className%}', '{%namespace%}', '{%app_namespace%}'], [
            $class,
            $namespace,
            App::getNamespace(),
        ], $stub);

    }

    protected function getPathName($name)
    {
        $appNamespace = App::getNamespace(); // app
        $name = str_replace(App::getNamespace() . '\\', '', $name);
        // 如果以app开头的 允许下面方式
        // 如果不是自定

        // Log::write(Env::get('app_path') );
        $app_path = Env::get('app_path');
        // return $app_path . ltrim(str_replace('\\', '/', $name), '/') . '.php';

        if (strpos($name, $appNamespace . '\\') !== false) {
            return $app_path . ltrim(str_replace('\\', '/', $name), '/') . '.php';
        } else {
            // 这里就是自定义了
            return str_replace('application/', '',$app_path) . ltrim(str_replace('\\', '/', $name), '/') . '.php';
        }
    }

    protected function getClassName($name) // $name => data\model\Test
    {
        // 获取系统的命名空间 app
        $appNamespace = App::getNamespace(); // app
        // 如果是以app命名开头的就会直接return
        if (strpos($name, $appNamespace . '\\') !== false) {
            return $name;
        }
        // $name data\model\Test
        if (Config::get('app_multi_module')) {
            // Config::get('app_multi_module') 定义了系统允许模块model，controller
            if (strpos($name, '/')) {
                list($module, $name) = explode('/', $name, 2);
            } else {
                // 如果命名空模块名没有定义的时候以common为文件命名
                $module = '';
            }
        } else {
            $module = null;
        }

        // 这是路径的处理
        if (strpos($name, '/') !== false) {
            $name = str_replace('/', '\\', $name);
        }
        return $name;
        // \n 
        // return $this->getNamespace($appNamespace, $module) . '\\' . $name;
    }
    // 这个方法就是完善命名空间的
    protected function getNamespace($appNamespace, $module)
    {
        return $module ? ($appNamespace . '\\' . $module) : $appNamespace;
    }

}
